package com.evil.common.sso.util;

import cn.hutool.crypto.digest.MD5;
import com.alibaba.fastjson.JSONObject;
import com.evil.common.core.enums.BaseEnum;
import com.evil.common.core.exception.BusinessException;
import com.evil.common.redis.constant.RedisConstant;
import com.evil.common.redis.util.RedisKeyUtil;
import com.evil.common.redis.util.RedisUtil;
import com.evil.common.sso.entity.SocketInfo;
import com.evil.common.sso.entity.User;
import com.evil.common.sso.enums.RCodeEnum;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import java.util.Optional;
import java.util.concurrent.TimeUnit;

/**
 * @author liyang
 * @date 2023-01-08 12:43
 */
@Slf4j
@Component
@AllArgsConstructor
public class TokenUtil {

    private final RedisUtil redisUtil;

    /**
     * 创建token
     *
     * @param user user
     * @return token
     */
    public <T extends User> String createToken(User user) {
        String token = (String) redisUtil.get(RedisKeyUtil.accessUserTokenKey(user.getUserId()));
        if (StringUtils.isNotBlank(token)) {
            return token;
        }
        token = MD5.create().digestHex(String.valueOf(user.getUserId()));

        String tokenKey = RedisKeyUtil.accessTokenKey(token);
        boolean setToken = redisUtil.set(tokenKey, user);
        if (!setToken) {
            throw new BusinessException(BaseEnum.ERROR);
        }
        boolean setUserToken = redisUtil.set(RedisKeyUtil.accessUserTokenKey(user.getUserId()), token);
        if (!setUserToken) {
            redisUtil.del(tokenKey);
            throw new BusinessException(BaseEnum.ERROR);
        }

        return token;
    }

    /**
     * 获取token 99999999999998
     *
     * @return TokenInfo
     */
    public User getLoginUser(String token) {
        Object o = redisUtil.get(RedisKeyUtil.accessTokenKey(token));
        User tokenInfo = null;
        if (o instanceof User u) {
            return u;
        }
        if (o instanceof JSONObject jsonObject) {
            tokenInfo = jsonObject.toJavaObject(User.class);
        }
        if (null == tokenInfo) {
            throw new BusinessException(RCodeEnum.ERROR_UNAUTHENTICATED);
        }
        return tokenInfo;
    }

    /**
     * 检查token
     *
     * @param token token
     */
    public void checkToken(String token) {
        Object o = redisUtil.get(RedisKeyUtil.accessTokenKey(token));
        if (null == o) {
            throw new BusinessException(RCodeEnum.ERROR_UNAUTHENTICATED);
        }
    }

    /**
     * 存socket token
     *
     * @param token      token
     * @param socketInfo socketInfo
     */
    public void setSocket(String token, SocketInfo socketInfo) {
        redisUtil.set(RedisKeyUtil.socketTokenKey(token), socketInfo, RedisConstant.TOKEN_EXPIRE_IN_SECOND, TimeUnit.SECONDS);
    }

    /**
     * 移除socket token
     *
     * @param token token
     */
    public void detSocket(String token) {
        redisUtil.del(RedisKeyUtil.socketTokenKey(token));
    }

    /**
     * 获取websocket认证信息
     *
     * @param token token
     * @return IP
     */
    public Optional<SocketInfo> isExistSocket(String token) {
        Object o;
        try {
            o = redisUtil.get(RedisKeyUtil.socketTokenKey(token));
        } catch (Exception e) {
            log.error("isExistToken| error: ", e);
            return Optional.empty();
        }
        SocketInfo socketInfo = null;
        if (o instanceof SocketInfo) {
            socketInfo = (SocketInfo) o;
        }
        if (o instanceof JSONObject jsonObject) {
            socketInfo = jsonObject.toJavaObject(SocketInfo.class);
        }
        return Optional.ofNullable(socketInfo);
    }
}
